from collections import defaultdict
import logging
import threading
import re


logging.basicConfig(level=logging.INFO)


class SearchLog:
    def __init__(self, log_file):
        self.file = open(log_file)
        self.logs = []
        self.url_result = defaultdict(int)
        self.response_result = defaultdict(int)
        self.url_compiler = re.compile(r'\d "(.*)" "M')
        self.response_compiler = re.compile(r" (\d{3}) ")
        self.lock = threading.Lock()

    def consumer(self):
        while True:
            try:
                with self.lock:
                    log = self.logs.pop()
            except IndexError:
                continue
            response_code_match = self.response_compiler.search(log)
            try:
                self.response_result[response_code_match.groups()[0]] += 1
            except Exception:
                continue
            url_match = self.url_compiler.search(log)
            try:
                self.url_result[url_match.groups()[0]] += 1
            except Exception:
                continue
            logging.info(f'url: {self.url_result}, '
                         f'response: {self.response_result}')

    def producer(self):
        while True:
            log = self.file.readline()
            with self.lock:
                self.logs.append(log)

    def start_search(self):
        producer = threading.Thread(target=self.producer, name='producer')
        consumer = threading.Thread(target=self.consumer, name='consumer')
        producer.start()
        consumer.start()

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()


if __name__ == '__main__':
    search_log = SearchLog('./access_2021_08_30.log')
    search_log.start_search()
